package generator.engine.impl;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import generator.engine.AbstractEngine;
import generator.entity.ClassInfo;
import generator.util.FreeMakerConfig;
import generator.util.GenConfig;
import generator.util.IOTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;


/**
 * @author chengsp
 * @date 2019/9/20 15:42
 */
public class DefaultEngine extends AbstractEngine {
    private final static Logger logger = LoggerFactory.getLogger(DefaultEngine.class);
    private GenConfig genConfig;
    private Configuration configuration = FreeMakerConfig.getConfiguration();

    public DefaultEngine(GenConfig genConfig) {
        this.genConfig = genConfig;
    }

    @Override
    public void genController(ClassInfo classInfo) {
        genClass(classInfo, "code-generator/mybatis-plus/pluscontroller.ftl", "controller", "Controller.java");
    }

    private void genClass(ClassInfo classInfo, String templateName, String parentPackage, String classSuffix) {
        String path = genConfig.getPackageName().replace(".", "/");
        String filePath = getRootPath() + "/src/main/java/" + path + "/" + parentPackage.replace(".",
                "/") + "/" + classInfo.getClassName() + classSuffix;
        process(classInfo, templateName, filePath);
    }

    private void process(ClassInfo classInfo, String templateName, String filePath) {
        try {
            File file = new File(filePath);
            if (file.exists() && genConfig.isOverride()) {
                return;
            }
            logger.info("文件名:{}", file.getAbsolutePath());
            file.getParentFile().mkdirs();
            Writer writer = new FileWriter(new File(filePath));
            Template template = configuration.getTemplate(templateName);
            Map<String, Object> params = new HashMap<>(16);
            params.put("classInfo", classInfo);
            params.put("authorName", genConfig.getAuthorName());
            params.put("packageName", genConfig.getPackageName());
            params.put("returnUtil", genConfig.getResultName());
            params.put("projectName", genConfig.getProjectName());
            params.put("genConfig", genConfig);
            template.process(params, writer);
            writer.flush();
            writer.close();
        } catch (IOException | TemplateException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void genService(ClassInfo classInfo) {
        // service
        genClass(classInfo, "code-generator/mybatis-plus/plusservice.ftl", "service", "Service.java");
        // serviceImpl
        genClass(classInfo, "code-generator/mybatis-plus/plusserviceimpl.ftl", "service.impl", "ServiceImpl.java");
    }

    @Override
    public void genRepositoryClass(ClassInfo classInfo) {
        genClass(classInfo, "code-generator/mybatis-plus/plusmapper.ftl", "mapper", "Mapper.java");
    }

    @Override
    public void genRepositoryXml(ClassInfo classInfo) {
        genClass(classInfo, "code-generator/mybatis/mybatis.ftl", "mapper", ".xml");
    }

    @Override
    public void genEntity(ClassInfo classInfo) {
        genClass(classInfo, "code-generator/mybatis/model2.ftl", "entity", ".java");
    }

    @Override
    public void genUi(ClassInfo classInfo) {
        // 查询页面
        genHtml(classInfo, "code-generator/ui/list.ftl", "list.html");
        // 添加页面
        genHtml(classInfo, "code-generator/ui/add.ftl", "add.html");
        genHtml(null, "code-generator/ui/index.ftl", "index.html");
    }

    private void genHtml(ClassInfo classInfo, String templateName, String fileName) {
        String dir = "";
        if (classInfo != null) {
            dir = classInfo.getTableName().toLowerCase() + "/";
        }
        String filePath = getRootPath() + "/src/main/resources/static/" + dir + fileName;
        process(classInfo, templateName, filePath);
    }

    private String getRootPath() {
        return genConfig.getRootPath() + "/" + genConfig.getProjectName();
    }

    @Override
    public void genConfig() {
        String rootPath = getRootPath();
        process(null, "code-generator/pom.ftl", rootPath + "/pom.xml");
        process(null, "code-generator/application.ftl", rootPath +
                "/src/main/resources/application.properties");
        process(null, "common/logback.ftl", rootPath + "/src/main/resources/logback.xml");
    }

    @Override
    public GenConfig getGenConfig() {
        return genConfig;
    }

    @Override
    public void genFix() {
        String rootPath = getRootPath();
        String basePath = rootPath + "/src/main/java/" + genConfig.getPackageName().replace(".", "/");
        process(null, "common/ApiResult.ftl", basePath + "/common/" + genConfig.getResultName() + ".java");
        process(null, "common/Application.ftl", basePath + "/Application.java");
        try {
            IOTool.loadRecourseFromJarByFolder("/templates/code-generator/ui/js",
                    rootPath + "/src/main/resources/static/", this.getClass(),
                    "/templates/code-generator/ui/js");
            IOTool.loadRecourseFromJarByFolder("/templates/code-generator/ui/lib",
                    rootPath + "/src/main/resources/static/", this.getClass(),
                    "/templates/code-generator/ui/lib");
            IOTool.loadRecourseFromJarByFolder("/templates/code-generator/ui/css",
                    rootPath + "/src/main/resources/static/", this.getClass(),
                    "/templates/code-generator/ui/css");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
